using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using RiceShop.Models;
using BCrypt.Net;
using Microsoft.EntityFrameworkCore;

namespace RiceShop.Services
{
    /// <summary>
    /// 管理员服务接口，提供管理员相关的业务操作。
    /// </summary>
    public interface IAdminService
    {
        IEnumerable<Admin> GetAllAdmins();
        Admin? GetAdminById(long id);
        Task<Admin> CreateAdminAsync(Admin admin);
        string? AuthenticateAdmin(string email, string password);
        Task<Admin> UpdateAdminAsync(Admin admin);
        void AssignRoleToAdmin(AssignRoleModel model);
        IEnumerable<long> GetRolesByAdminId(long adminId);
        IEnumerable<Admin> GetAdmins(string search, string sortBy, bool ascending, int page, int pageSize);
        int GetAdminsCount(string search);
        bool AdminExists(long id);
        bool DeleteAdmin(long id);
        TokenResult? AuthenticateAdminByAdminname(string adminname, string password);
        TokenResult? RefreshToken(string refreshToken);
        // 添加新方法
        bool ValidatePassword(string password, string hashedPassword);
    }

    /// <summary>
    /// 管理员服务实现类，处理管理员相关的业务逻辑。
    /// </summary>
    public class AdminService : IAdminService
    {
        private readonly ApplicationDbContext _context;
        private readonly IConfiguration _configuration;

        public AdminService(ApplicationDbContext context, IConfiguration configuration)
        {
            _context = context;
            _configuration = configuration;
        }

        /// <summary>
        /// 获取所有管理员。
        /// </summary>
        /// <returns>管理员列表。</returns>
        public IEnumerable<Admin> GetAllAdmins()
        {
            // 从数据库中获取所有管理员
            return _context.Admins.ToList();
        }

        /// <summary>
        /// 根据管理员ID获取管理员信息。
        /// </summary>
        /// <param name="id">管理员ID。</param>
        /// <returns>管理员信息。</returns>
        public Admin? GetAdminById(long id)
        {
            var admin = _context.Admins.Find(id);
            return admin;
        }

        /// <summary>
        /// 创建新管理员。
        /// </summary>
        /// <param name="admin">管理员信息。</param>
        /// <returns>创建的管理员信息。</returns>
        public async Task<Admin> CreateAdminAsync(Admin admin)
        {
            admin.adminCtime = DateTime.UtcNow;
            admin.adminUtime = DateTime.UtcNow;

            _context.Admins.Add(admin);
            await _context.SaveChangesAsync();
            return admin;
        }

        /// <summary>
        /// 验证用户凭证并生成JWT令牌。
        /// </summary>
        /// <param name="email">管理员邮箱。</param>
        /// <param name="password">管理员密码。</param>
        /// <returns>JWT 令牌。</returns>
        public string? AuthenticateAdmin(string email, string password)
        {
            var admin = _context.Admins.SingleOrDefault(a => a.adminEmail == email && a.adminPassword == password);
            if (admin == null)
            {
                return null;
            }

            // 生成 JWT 令牌（此处省略具体实现）
            return "generated-jwt-token";
        }

        /// <summary>
        /// 更新用户信息。
        /// </summary>
        /// <param name="admin">更新后的管理员信息。</param>
        public async Task<Admin> UpdateAdminAsync(Admin admin)
        {
            admin.adminUtime = DateTime.UtcNow;


            _context.Admins.Update(admin);
            await _context.SaveChangesAsync();
            return admin;
        }

        /// <summary>
        /// 为用户分配角色。
        /// </summary>

        public void AssignRoleToAdmin(AssignRoleModel model)
        {
            // 确保用户存在
            var admin = _context.Admins.Find(model.AdminId);
            if (admin == null)
            {
                throw new ArgumentException("Admin not found", nameof(model.AdminId));
            }


            _context.AdminRoles.RemoveRange(_context.AdminRoles.Where(ar => ar.adminId == model.AdminId));




            foreach (var roleId in model.Roles)
            {
                // 添加新的角色分配
                _context.AdminRoles.Add(new AdminRole
                {
                    adminId = model.AdminId,
                    roleId = roleId
                });

            }


            _context.SaveChanges();

        }

        /// <summary>
        /// 获取管理员的角色列表。
        /// </summary>
        /// <param name="adminId">管理员ID。</param>
        /// <returns>角色ID列表。</returns>
        public IEnumerable<long> GetRolesByAdminId(long adminId)
        {
            return _context.AdminRoles
                .Where(ar => ar.adminId == adminId)
                .Select(ar => ar.roleId)
                .ToList();
        }

        /// <summary>
        /// 获管理员列表。
        /// </summary>
        /// <param name="search">搜索关键字。</param>
        /// <param name="sortBy">排序字段。</param>
        /// <param name="ascending">是否升序排序。</param>
        /// <param name="page">页码。</param>
        /// <param name="pageSize">每页记录数。</param>
        /// <returns>管理员列表。</returns>
        public IEnumerable<Admin> GetAdmins(
            string search,
            string sortBy,
            bool ascending,
            int page,
            int pageSize)
        {
            var query = _context.Admins.AsQueryable();

            if (!string.IsNullOrEmpty(search))
            {
                query = query.Where(a => a.adminName.Contains(search) || (a.adminEmail != null && a.adminEmail.Contains(search)));
            }

            switch (sortBy.ToLower())
            {
                case "email":
                    query = ascending ? query.OrderBy(a => a.adminEmail) : query.OrderByDescending(a => a.adminEmail);
                    break;
                default:
                    query = ascending ? query.OrderBy(a => a.adminName) : query.OrderByDescending(a => a.adminName);
                    break;
            }
            var totalCount = query.Count();

            return query.Skip((page - 1) * pageSize).Take(pageSize).ToList();

        }
        public int GetAdminsCount(string search)
        {
            var query = _context.Admins.AsQueryable();

            if (!string.IsNullOrEmpty(search))
            {
                query = query.Where(a => a.adminName.Contains(search) || (a.adminEmail != null && a.adminEmail.Contains(search)));
            }

            return query.Count();
        }





        // 在此处添加您的服务方法

        // 实现会话管理逻辑

        // 添加 AdminExists 方法
        public bool AdminExists(long id)
        {
            return _context.Admins.Any(a => a.adminId == id);
        }

        /// <summary>
        /// 删除用户。
        /// </summary>
        /// <param name="id">管理员ID。</param>
        /// <returns>是否成功删除。</returns>
        public bool DeleteAdmin(long id)
        {
            var admin = _context.Admins.Find(id);
            if (admin == null)
            {
                return false;
            }

            _context.Admins.Remove(admin);
            _context.SaveChanges();
            return true;
        }

        /// <summary>
        /// 通过管理员名和密码进行身份验证。
        /// </summary>
        /// <param name="adminname">管理员名</param>
        /// <param name="password">密码</param>
        /// <returns>令牌结果，包含访问令牌和刷新令牌</returns>
        public TokenResult? AuthenticateAdminByAdminname(string adminname, string password)
        {
            // 获取管理员
            var admin = _context.Admins.SingleOrDefault(a => a.adminName == adminname);
            if (admin == null) return null;

            // 验证密码哈希
            if (!BCrypt.Net.BCrypt.Verify(password, admin.adminPassword))
            {
                return null;
            }

            return GenerateTokens(admin);
        }

        /// <summary>
        /// 使用刷新令牌获取新的访问令牌。
        /// </summary>
        /// <param name="refreshToken">刷新令牌</param>
        /// <returns>新的令牌结果</returns>
        public TokenResult? RefreshToken(string refreshToken)
        {
            // 验证刷新令牌
            var principal = ValidateRefreshToken(refreshToken);
            if (principal == null)
            {
                return null;
            }

            // 获取用户ID
            var adminIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier);
            if (adminIdClaim == null || !long.TryParse(adminIdClaim.Value, out long adminId))
            {
                return null;
            }

            // 获取用户
            var admin = GetAdminById(adminId);
            if (admin == null)
            {
                return null;
            }

            // 生成新的令牌
            return GenerateTokens(admin);
        }

        /// <summary>
        /// 生成访问令牌和刷新令牌。
        /// </summary>
        /// <param name="admin">管理员信息</param>
        /// <returns>令牌结果</returns>
        private TokenResult GenerateTokens(Admin admin)
        {
            var accessToken = GenerateJwtToken(admin);
            var refreshToken = GenerateRefreshToken();
            var expiresAt = DateTime.UtcNow.AddMinutes(30);

            return new TokenResult
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                ExpiresAt = expiresAt
            };
        }

        /// <summary>
        /// 生成刷新令牌。
        /// </summary>
        /// <returns>刷新令牌字符串</returns>
        private string GenerateRefreshToken()
        {
            var randomNumber = new byte[32];
            using var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
            rng.GetBytes(randomNumber);
            return Convert.ToBase64String(randomNumber);
        }

        /// <summary>
        /// 验证刷新令牌的有效性。
        /// </summary>
        /// <param name="refreshToken">刷新令牌</param>
        /// <returns>令牌中包含的身份信息</returns>
        private ClaimsPrincipal? ValidateRefreshToken(string refreshToken)
        {
            var tokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = _configuration["Jwt:Issuer"],
                ValidAudience = _configuration["Jwt:Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"] ?? throw new InvalidOperationException("JWT Key is not configured."))),
                // 添加时钟偏移容差
                ClockSkew = TimeSpan.Zero  // 不允许任何时钟偏移，使过期检查更精确
            };

            try
            {
                var tokenHandler = new JwtSecurityTokenHandler();
                var principal = tokenHandler.ValidateToken(refreshToken, tokenValidationParameters, out SecurityToken validatedToken);

                // 额外验证令牌类型
                if (!(validatedToken is JwtSecurityToken jwtToken) ||
                    !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
                {
                    return null;
                }

                return principal;
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 生成JWT访问令牌。
        /// </summary>
        /// <param name="admin">管理员信息</param>
        /// <returns>JWT令牌字符串</returns>
        private string GenerateJwtToken(Admin admin)
        {
            // 从配置文件中读取 JWT 设置
            var jwtSettings = _configuration.GetSection("Jwt");
            var key = jwtSettings["Key"] ?? throw new InvalidOperationException("JWT Key is not configured.");
            var issuer = jwtSettings["Issuer"];
            var audience = jwtSettings["Audience"];

            // 定义令牌的有效载荷
            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier, admin.adminId.ToString()), // 修改这行
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(ClaimTypes.Name, admin.adminName)
            };

            // 定义密钥和加密算法
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
            var creds = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            // 创建令牌
            var token = new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                claims: claims,
                expires: DateTime.Now.AddMinutes(30), // 使用 DateTime.UtcNow 而不是 DateTime.Now
                signingCredentials: creds);

            // 返回序列化的令牌
            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        public bool ValidatePassword(string password, string hashedPassword)
        {
            return BCrypt.Net.BCrypt.Verify(password, hashedPassword);
        }
    }
}
